package com.milhouz.quizzdroid;

import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.milhouz.quizzdroid.bean.Game;
import com.milhouz.quizzdroid.bean.Game.GameMode;
import com.milhouz.quizzdroid.bean.Question;
import com.milhouz.quizzdroid.bean.User;
import com.milhouz.quizzdroid.db.QuizzDroidConstants;
import com.milhouz.quizzdroid.db.QuizzDroidDbAPI;
import com.milhouz.quizzdroid.dialog.GamePauseDialog;
import com.milhouz.quizzdroid.exception.DatabaseRequestException;
import com.milhouz.quizzdroid.view.AvatarUtil;
import com.milhouz.quizzdroid.view.IResponsesLayout;
import com.milhouz.quizzdroid.view.OnResponseListener;
import com.milhouz.quizzdroid.view.ResponseListLayout;

public class QuizzDroidGameActivity extends Activity implements TextToSpeech.OnInitListener {

	// Views
	private static FrameLayout mQuestionContainer;
	private static TextView mCategoryLabel;
	private static TextView mTeamLabel;
	private static TextView mScore;
	private static TextView mQuestionLabel;
	private static IResponsesLayout mResponsesLayout;
	private static ProgressBar mTimerProgressBar;
	private static ImageView mAvatarImg;
	private static ImageView mWikiLink;

	// Animations
	private static Animation mStretch;
	private static Animation mUnstretch;
	// TextToSpeech
	private static TextToSpeech mTts;
	// CountDown
	private static CountDown mCountdown;
	// Game Settings bean
	private static Game mGame;
	// Current Question Bean
	private static Question mCurrentQuestion;
	// Is end of question ?
	private static boolean isEndOfQuestion;
	private long startQuestionTime;

	private static Set<Integer> mQuestionsAsked = new HashSet<Integer>();
	private final static int NB_MAX_TRIES = 3;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Set window content (with fullscreen mode)
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.game);

		// Game Settings
		mGame = getIntent().getExtras().getParcelable(getString(R.string.intent_extra_game));
		mGame.initPlayers();

		Log.i(QuizzDroidConstants.TAG, "Game = " + mGame);

		// Views
		mScore = (TextView) findViewById(R.id.score);
		mTeamLabel = (TextView) findViewById(R.id.teamLabel);
		mCategoryLabel = (TextView) findViewById(R.id.categoryLabel);
		mQuestionLabel = (TextView) findViewById(R.id.questionLabel);
		mTimerProgressBar = (ProgressBar) findViewById(R.id.timerProgressBar);
		mResponsesLayout = (ResponseListLayout) findViewById(R.id.responses);
		mQuestionContainer = (FrameLayout) findViewById(R.id.questionContainer);
		mAvatarImg = (ImageView) findViewById(R.id.avatarImg);
		mWikiLink = (ImageView) findViewById(R.id.wikiLink);
		mWikiLink.setVisibility(View.INVISIBLE);

		// Animations
		mStretch = AnimationUtils.loadAnimation(this, R.anim.stretch);
		mUnstretch = AnimationUtils.loadAnimation(this, R.anim.unstretch);

		// Activate TextToSpeech
		if (mGame.isTextToSpeech()) {
			mTts = new TextToSpeech(this, this);
		}

		// Activate CountDown
		if (mGame.isCountDown()) {
			mCountdown = new CountDown(mTimerProgressBar, mGame.getCountDownTime()) {
				@Override
				public void onFinishCountdown() {
					cancel();
					onUserAnswer(-1);
				}
			};
		} else {
			mTimerProgressBar.setVisibility(View.INVISIBLE);
		}

		// Add animation listener
		mStretch.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation arg0) {
			}

			@Override
			public void onAnimationRepeat(Animation arg0) {
			}

			@Override
			public void onAnimationEnd(Animation arg0) {
				updateAndShowQuestionContainer();
			}
		});

		// Start the game (if not tts, the game will start when tts is initialized)
		if (!mGame.isTextToSpeech()) {
			selectAndShowRandomQuestion();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (isEndOfQuestion) {
			// Select next question
			selectAndShowRandomQuestion();
		}
		return false;
	}

	private void onUserAnswer(int position) {
		// Stop sounds if speaking
		if (mTts != null && mTts.isSpeaking()) {
			mTts.stop();
		}
		// Set wikilink view
		if (mCurrentQuestion.getWikiLink() != null) {
			mWikiLink.setVisibility(View.VISIBLE);
			mWikiLink.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View arg0) {
					Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mCurrentQuestion.getWikiLink()));
					startActivity(browserIntent);
				}
			});
		}
		if (!isEndOfQuestion) {
			// Stop Countdown
			if (mGame.isCountDown()) {
				mCountdown.cancel();
			}
			// Show correct response
			mResponsesLayout.showCorrectResponse();
			float meantime = (System.nanoTime() - startQuestionTime) / 1000000;
			// Is correct response ?
			if (position != -1 && mCurrentQuestion.getResponses().get(position).isCorrectResponse()) { // YES
				// Update avatar
				mAvatarImg.setImageDrawable(AvatarUtil.getAvatarByResponse(this, true));
				// Update score
				mGame.getCurrentPlayer().getScore().addCorrectResponses();
				mGame.getCurrentPlayer().getScore().addResponseTime(meantime);
				mScore.setText(mGame.getCurrentPlayer().getPlayerScore());
				updateGlobalUserStats(true, meantime);
				// TODO : Play a sound Yeah!
			} else { // NO
				// Update avatar
				mAvatarImg.setImageDrawable(AvatarUtil.getAvatarByResponse(this, false));
				// Play the response
				updateGlobalUserStats(false, meantime);
				if (mTts != null) {
					mTts.speak("La réponse est : " + mCurrentQuestion.getResponse(), TextToSpeech.QUEUE_FLUSH, null);
				}
			}
			isEndOfQuestion = true;
		} else {
			// Select next question
			selectAndShowRandomQuestion();
		}
		// Set next player
		mGame.setNextPlayer();
	}

	/**
	 * Select randomly a question from the database
	 */
	private void selectAndShowRandomQuestion() {
		isEndOfQuestion = false;
		// Select random question into database
		int nbTries = 0;
		do {
			try {
				mCurrentQuestion = QuizzDroidDbAPI.getInstance().getRandomQuestion(this);
				nbTries++;
			} catch (DatabaseRequestException e) {
				Log.w(QuizzDroidConstants.TAG, "Database request error, try again...", e);
			}
		} while (mQuestionsAsked.contains(mCurrentQuestion.getId()) && nbTries < NB_MAX_TRIES);
		mQuestionsAsked.add(mCurrentQuestion.getId());

		// Update and launch question container stretch animation
		startQuestionTime = System.nanoTime();
		mQuestionContainer.startAnimation(mStretch);
	}

	public void updateAndShowQuestionContainer() {
		// Update statistics
		mGame.getCurrentPlayer().getScore().addNbQuestions();

		// Update Views
		mScore.setText(mGame.getCurrentPlayer().getPlayerScore());
		mQuestionLabel.setText(mCurrentQuestion.getQuestion());
		mResponsesLayout.setQuestion(mCurrentQuestion);
		mCategoryLabel.setText(mCurrentQuestion.getCategory().getLabel());
		mAvatarImg.setImageDrawable(AvatarUtil.getWhatAvatar(this));
		mWikiLink.setVisibility(View.INVISIBLE);
		if (mGame.getGameMode().equals(GameMode.MULTIPLAYER)) {
			mTeamLabel.setText(String.format(getString(R.string.game_multiplayer_teamname), mGame.getCurrentPlayer().getPlayerNumber()));
		}

		// Set responses listener
		mResponsesLayout.setOnResponseListener(new OnResponseListener() {
			@Override
			public void onSelectResponse(int indexResponse) {
				onUserAnswer(indexResponse);
			}
		});
		// Launch question container unstretch animation
		mQuestionContainer.startAnimation(mUnstretch);
		// Play the question via TextToSpeech
		if (mTts != null) {
			mTts.speak("Catégorie : " + mCurrentQuestion.getCategory().getLabel() //
					+ ", " + mCurrentQuestion.getQuestion(), TextToSpeech.QUEUE_FLUSH, null);
		}
		// Countdown start
		if (mGame.isCountDown()) {
			mCountdown.start();
		}
	}

	@Override
	public void onInit(int status) {
		if (mTts != null) {
			// status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR.
			if (status == TextToSpeech.SUCCESS) {
				// Set preferred language to US english.
				// Note that a language may not be available, and the result will indicate this.
				int result = mTts.setLanguage(Locale.FRENCH);
				// Try this someday for some interesting results.
				// int result mTts.setLanguage(Locale.FRANCE);
				if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
					// Lanuage data is missing or the language is not supported.
					Log.e(QuizzDroidConstants.TAG, "[TTS] Language is not available.");
				} else {
					// Check the documentation for other possible result codes.
					// For example, the language may be available for the locale,
					// but not for the specified country and variant.
					Log.i(QuizzDroidConstants.TAG, "[TTS] The TTS engine has been successfully initialized.");
				}
			} else {
				// Initialization failed.
				Log.e(QuizzDroidConstants.TAG, "[TTS] Could not initialize TextToSpeech.");
			}
			selectAndShowRandomQuestion();
		}
	}

	private void updateGlobalUserStats(boolean isGoodResponse, float meantime) {
		if (mGame.getGameMode().equals(GameMode.SINGLE)) {
			// Request current user stat
			User user = QuizzDroidDbAPI.getInstance().getDefaultUser(this);
			if (user != null) {
				user.updateStats(isGoodResponse, meantime);
				QuizzDroidDbAPI.getInstance().updateUser(this, user);
			} else {
				Log.w(QuizzDroidConstants.TAG, "User bean not found in the database");
			}
		}
	}

	GamePauseDialog mPauseDialog = null;

	@Override
	public void onBackPressed() {
		// TODO pause mCountdown.
		onPauseGame();
		if (mPauseDialog == null) {
			mPauseDialog = new GamePauseDialog(QuizzDroidGameActivity.this, mGame);
		}
		mPauseDialog.showPauseDialog(mGame);
	}

	public void onPauseGame() {
		if (mTts != null) {
			mTts.stop();
		}
		if (mCountdown != null) {
			mCountdown.cancel();
		}
	}

	public void onResumeGame() {
		// Activate CountDown
		if (mGame.isCountDown()) {
			mCountdown = new CountDown(mTimerProgressBar, mGame.getCountDownTime()) {
				@Override
				public void onFinishCountdown() {
					cancel();
					onUserAnswer(-1);
				}
			};
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		outState.putParcelable("game", mGame);
		outState.putParcelable("question", mCurrentQuestion);
		outState.putBoolean("isEndOfQuestion", isEndOfQuestion);
		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		mGame = savedInstanceState.getParcelable("game");
		mCurrentQuestion = savedInstanceState.getParcelable("question");
		isEndOfQuestion = savedInstanceState.getBoolean("isEndOfQuestion");
		startQuestionTime = System.nanoTime();
	}

	@Override
	public void onDestroy() {
		if (mTts != null) {
			mTts.stop();
			mTts.shutdown();
		}
		super.onDestroy();
	}

}
